package edu.config;

import com.alibaba.fastjson.JSONObject;
import edu.config.security.DbUserDetailsService;
import edu.config.security.SimplePasswordEncoder;
import edu.domain.User;
import edu.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import javax.servlet.http.HttpSession;

/**
 *
 * @date 9:37
 */
@Configuration
@EnableWebSecurity
// 开启security注解
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


    private static final Logger logger = LoggerFactory.getLogger(WebSecurityConfig.class);

    @Autowired
    private DbUserDetailsService dbUserDetailsService;
    @Autowired
    private UserService userService;


    /**
     * 设置验证信息
     *
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(dbUserDetailsService)
                .passwordEncoder(passwordEncoder());
    }

    /**
     * 配置忽略的请求
     *
     * @param web
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        // 下面这行是放行所有请求，不校验权限
        // web.debug(true);
        super.configure(web);
    }

    /**
     * 设置权限信息
     *
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 主要是看UrlMatchVoter,所有的权限检查都在UrlMatchVoter
        http.cors()
                .and()
                .csrf().disable()
                // iframe 嵌套
                .headers().frameOptions().disable()
                .and()

                // 登录拦截器
                .formLogin()
                .successHandler((request, response, authentication) -> {
                    logger.info("【登录成功】  用户：{} ", JSONObject.toJSONString(authentication));
                    User user = userService.getOne("username", authentication.getName());
                    HttpSession session = request.getSession();
                    session.setAttribute("loginUser", user);
                    session.setAttribute("loginUserId", user.getId());
                    // 跳转到首页
                    response.sendRedirect("/");
                })
                .failureHandler((request, response, exception) -> {
                    logger.warn("【登录失败】  原因：" + exception.getLocalizedMessage(), exception);
                    // 跳转到登录页
                    request.setAttribute("message", "用户名或密码错误");
                    request.getRequestDispatcher("/login").forward(request, response);
                })
                // 登录地址
                .loginProcessingUrl("/loginAuth")
                // 退出地址
                .and().logout().logoutUrl("/logout")
                // 退出登录
                .logoutSuccessHandler((request, response, authentication) -> {
                    logger.info("【退出登录】  用户：{}", authentication.getName());
                    HttpSession session = request.getSession();
                    session.removeAttribute("loginUser");
                    session.removeAttribute("loginUserId");
                    // 跳转到首页
                    response.sendRedirect("/");
                })


                // 配置访问权限
                .and().authorizeRequests()
                // 所有用户可以访问
                .antMatchers("/test",
                        "/webjars/**", "/plugins/**", "/css/**", "/images/**", "/assets/**",
                        "/noAuth", "/login", "/register",
                        "/", "/goods/list", "/goods/detail/**",
                        "/common/**", "/upload/**", "/ueditor/**"
                ).permitAll()
                // 需要验证权限
                .anyRequest().authenticated()
                .and()

                .exceptionHandling()
                // 没有登录
                .authenticationEntryPoint((req, resp, authException) -> {
                    logger.error("请先登录 : {}", authException.getLocalizedMessage());
                    // 跳转登录页
                    resp.sendRedirect("/login");
                })
                // 没有权限
                .accessDeniedHandler((request, response, accessDeniedException) -> {
                    logger.error("没有权限:{}", accessDeniedException.getLocalizedMessage());
                    // 跳转没权限页
                    response.sendRedirect("/noAuth");
                })
        ;
    }


    /**
     * 加密策略
     *
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        // 加密
        return new BCryptPasswordEncoder();

        // 不加密
       // return new SimplePasswordEncoder();
    }


}
